package com.learn.training.multithread.chapter10.demo1;

import java.util.concurrent.RecursiveTask;

public class RecursiveTaskExample extends RecursiveTask<Long> {

    static final int THRESHOLD = 500;
    long[] array;
    int start;
    int end;

    RecursiveTaskExample(long[] array, int start, int end) {
        this.array = array;
        this.start = start;
        this.end = end;
    }

    @Override
    protected Long compute() {
        if (end - start <= THRESHOLD) {
            // 如果任务足够小,直接计算
            long sum = 0;
            for (int i = start; i < end; i++) {
                sum += array[i];
            }
            System.out.println(String.format("Task [%d~%d] executed by thread: %s at %d", start, end, Thread.currentThread().getName(), System.currentTimeMillis()));
            return sum;
        }

        // 任务太大,一分为二:
        int middle = (start + end) / 2;
        System.out.println(String.format("split %d~%d ==>  %d~%d, %d~%d", start, end, start, middle, middle, end));
        RecursiveTaskExample subTask1 = new RecursiveTaskExample(this.array, start, middle);
        RecursiveTaskExample subTask2 = new RecursiveTaskExample(this.array, middle, end);
        // invokeAll会并行运行两个子任务:
        // 注意: 子任务之间的关系是"同步"关系,即 subTask1 和 subTask2 会同时开始执行。
        // 而子任务与父任务的关系是"异步"关系,即父任务不会等待子任务执行完,而是继续执行后面的代码，等待子任务完成后再获取结果。
        // 所以,在父任务中,我们需要使用join()方法来等待子任务执行完,然后再获取子任务的结果.
        // 这样,父任务才能正确地获取子任务的结果,从而正确地计算出最终的结果.
        invokeAll(subTask1, subTask2);
        long subResult1 = subTask1.join();
        long subResult2 = subTask2.join();
        long result = subResult1 + subResult2;
        System.out.println(String.format("result : " + subResult1 + "  +  " +  subResult2 + "  =  " + result));
        return result;
    }
}
